package se.webbzon.oschi01.textureset;

import java.awt.Container;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.media.j3d.Texture;

import com.sun.j3d.utils.image.TextureLoader;

import se.webbzon.oschi01.resourceset.ResourceSetLoader;
import se.webbzon.oschi01.resourceset.ResourceSetLoaderException;

public class Texture3DSetLoader extends ResourceSetLoader<Texture3D> {
	
	/*============================================================
	Public Methods
	============================================================*/

	@Override public boolean supportsAddFromURL() {
		return true;
	}

	@Override public boolean addFromURL(URL resourceURL) throws ResourceSetLoaderException {
		try {
			return addResource(new URLTexture3D(resourceURL));
		} catch (Exception e) {
			throw new ResourceSetLoaderException(e);
		}
	}

	@Override public boolean supportsAddFromInputStream() {
		return true;
	}

	@Override public boolean addFromInputStream(InputStream inputStream) throws ResourceSetLoaderException {
		try {
			return addFromBufferedImage(ImageIO.read(inputStream));
		} catch (IOException e) {
			throw new ResourceSetLoaderException(e);
		}
	}
	
	/** Adds a new Textur3D to the Texture3DSetLoader from a buffered image. **/
	public boolean addFromBufferedImage(BufferedImage image) throws ResourceSetLoaderException {
		return addResource(new BufferedTexture3D(image));
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	/** An abstraction of a texture. **/
	private static abstract class AbstractTexture3D extends Texture3D {

		/** The TextureLoader associated with this Texture3D. **/
		private TextureLoader loader;
		
		/*============================================================
		Public Methods
		============================================================*/
		
		@Override public Texture getTexture() {
			if (loader == null) {
				loader = createLoader();
				loader.getTexture().setMagFilter(Texture.BASE_LEVEL_POINT);
				loader.getTexture().setMinFilter(Texture.BASE_LEVEL_POINT);
			}
			return loader.getTexture();
		}

		@Override public Image getImage() {
			if (loader == null) {
				loader = createLoader();
				loader.getTexture().setMagFilter(Texture.BASE_LEVEL_POINT);
				loader.getTexture().setMinFilter(Texture.BASE_LEVEL_POINT);
			}
			return loader.getImage().getImage();
		}
		
		/*============================================================
		Protected Methods
		============================================================*/
		
		/** Creates a new texture loader for this texture. **/
		protected abstract TextureLoader createLoader();
		
	}
	
	/** An URL loaded texture. **/
	private static final class URLTexture3D extends AbstractTexture3D {
		
		private final URL url;
		
		public URLTexture3D(URL url) {
			this.url = url;
		}

		@Override protected TextureLoader createLoader() {
			return new TextureLoader(url,"RGBA",TextureLoader.GENERATE_MIPMAP,new Container());
		}
		
	}
	
	/** A buffered texture. **/
	private static final class BufferedTexture3D extends AbstractTexture3D {
		
		private final BufferedImage img;
		
		public BufferedTexture3D(BufferedImage img) {
			this.img = img;
		}

		@Override protected TextureLoader createLoader() {
			return new TextureLoader(img);
		}
		
	}
	
}
